package com.tanglon.listener.read;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.tanglon.domain.dto.ExcelUserDTO;
import com.tanglon.mapper.UserMapper;
import com.tanglon.service.UserService;
import com.tanglon.task.DeadMainThread;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;


/**
 * 用户导入（多线程）
 */

public class MutliReadListener extends AnalysisEventListener<ExcelUserDTO> {



    private PasswordEncoder passwordEncoder;

    // 注入UserService，用于传递给线程
    private UserService userService;

    public MutliReadListener() {

    }

    public MutliReadListener(PasswordEncoder passwordEncoder, UserService userService) {
        this.passwordEncoder = passwordEncoder;
        this.userService = userService;
    }


    /**
     * 线程安全集合
     */
    private List<ExcelUserDTO> dataList = Collections.synchronizedList(new ArrayList<>());


    /**
     * 创建线程池必要参数
     */
    private static final int CORE_POOL_SIZE = 5;//核心线程数
    private static final int MAX_POOL_SIZE = 10;//最大线程数
    private static final int QUEUE_CAPACITY = 100;//队列大小
    private static final Long KEEP_ALIVE_TIME = 1L;//存活时间

    /**
     * 将总数据添加到集合中
     * @param excelUserDTO
     * @param analysisContext
     */
    @Override
    public void invoke(ExcelUserDTO excelUserDTO, AnalysisContext analysisContext) {
            //加密
            System.out.println(excelUserDTO);
            dataList.add(excelUserDTO);
    }

    /**
     * 开启线程池处理数据
     * @param analysisContext
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {

        if (dataList.isEmpty()) {
            return; // 无数据时直接返回
        }

        //创建线程池
        ExecutorService executor =new ThreadPoolExecutor(CORE_POOL_SIZE,
                MAX_POOL_SIZE,
                KEEP_ALIVE_TIME,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(QUEUE_CAPACITY),
                new ThreadPoolExecutor.CallerRunsPolicy());
        //指定每个线程需要处理的导入数量，每个线程处理10000条
        int singleThreadDealCount = 10000;
        //根据假设每个线程需要处理的数量以及总数，计算需要提交到线程池的线程数量
        int threadsize =(dataList.size()/singleThreadDealCount)+1;
        System.out.println("threadsize==>"+threadsize);
        //计算需要导入的数据总数，用于拆分时线程需要处理数据时使用
        int rowsize =dataList.size()+1;
        //测试开始时间
        long startTime = System.currentTimeMillis();

        //该线程需要处理数据开始的位置
        int start = 0;
        //该线程需要处理数据结束位置
        int end = 0;

        CountDownLatch countDownLatch = new CountDownLatch(threadsize);
        //计算每个线程要处理的数据
        for(int i=0; i<threadsize; i++){
            if((i+1)==threadsize){
                start = ( i * singleThreadDealCount );
                end = rowsize - 1;
            }
            else{
                start = ( i * singleThreadDealCount );
                end = ( i + 1 ) * singleThreadDealCount;
            }

            System.out.println("线程开启-------count:"+countDownLatch+"start:"+start+"end:"+end);
            DeadMainThread task = new DeadMainThread(countDownLatch, dataList, start, end, userService);
            executor.execute(task);
        }
        try{
            countDownLatch.await();
        }catch (InterruptedException e){
            e.printStackTrace();
        }

        //关闭线程池
        executor.shutdown();
        long endTime = System.currentTimeMillis();
        System.out.println("总耗时："+(endTime-startTime));

    }

}
